﻿﻿// Introduction to Neural Networks for C#, 2nd Edition
// Copyright 2008 by Heaton Research, Inc. 
// http://www.heatonresearch.com/online/introduction-neural-networks-cs-edition-2
//         
// ISBN13: 978-1-60439-009-4  	 
// ISBN:   1-60439-009-3
//   
// This class is released under the:
// GNU Lesser General Public License (LGPL)
// http://www.gnu.org/copyleft/lesser.html

namespace WindowsFormsGUI.Entidades
{
    public class HopfieldNetwork
    {
        /// <summary>
        /// The weight matrix.
        /// </summary>
        private float[][] _weightMatrix;

        /// <summary>
        /// Construct a Hopfield neural network of the specified size.
        /// </summary>
        /// <param name="size">The number of neurons in the network.</param>
        public HopfieldNetwork(int size)
        {
            this._weightMatrix = new float[size][];

            for (int i = 0; i < size; i++)
            {
                this._weightMatrix[i] = new float[size];
            }
        }

        /// <summary>
        /// Present a pattern to the neural network and receive the result.
        /// </summary>
        /// <param name="pattern">The pattern to be presented to the neural network.</param>
        /// <returns>The output from the neural network.</returns>
        public float[] Present(float[] pattern)
        {
            float[] output = new float[pattern.Length];

            // Process each value in the pattern
            for (int col = 0; col < pattern.Length; col++)
            {
                // Multiply the input for each row
                float dotProduct = (float) 0.0;

                for (int i = 0; i < pattern.Length; i++)
                {
                    dotProduct += pattern[i] * _weightMatrix[col][i];
                }

                // Convert the dot product to either true or false.
                if (dotProduct > 0)
                {
                    output[col] = 1;
                }
                else
                {
                    output[col] = -1;
                }
            }

            return output;
        }


        /// <summary>
        /// Train the neural network for the specified pattern. The neural network
        /// can be trained for more than one pattern. To do this simply call the
        /// train method more than once. 
        /// </summary>
        /// <param name="pattern">The pattern to train on.</param>
        public void Train(float[] pattern)
        {
            // Transpose the matrix and multiply by the original input matrix
            for (int i = 0; i < pattern.Length; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    _weightMatrix[i][j] = _weightMatrix[i][j] + pattern[i] * pattern[j];
                    _weightMatrix[j][i] = _weightMatrix[i][j];
                }

                _weightMatrix[i][i] = _weightMatrix[i][i] + (pattern[i] * pattern[i]) - 1;
            }
        }
    }
}